--------------------------------------------------------------------------------
--!	@file	sm.lua
--!	@brief
--!		SM test file
--!
--!	@Description
--!		This program demonstrates a class+object named SM:
--!
--!	Creation Date:	3/3/2013
--!
--!	$Id: sm.lua 170 2013-03-12 05:01:32Z ac.verbeck@gmail.com $
--------------------------------------------------------------------------------

--------------------------------------------------------------------------------
--	Copyright and Disclaimer Notice
--
--	Copyright (c) 2013 A.C. Verbeck
--
--	This file is part of SM: A State Machine Library.
--
--	SM is free software: you can redistribute it and/or modify
--	it under the terms of the GNU General Public License as published by
--	the Free Software Foundation, either version 3 of the License, or
--	(at your option) any later version.
--
--	SM is distributed in the hope that it will be useful,
--	but WITHOUT ANY WARRANTY; without even the implied warranty of
--	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--	GNU General Public License for more details.
--
--	You should have received a copy of the GNU General Public License
--	along with SM.  If not, see <http://www.gnu.org/licenses/>.
--
--------------------------------------------------------------------------------

--------------------------------------------------------------------------------
--
--	State processing functions
--
--------------------------------------------------------------------------------
function def_enter()
	print("default: enter")
end

function def_process(event)
	print("default: process")
	sm:new_state(2)
end

function def_exit()
	print("default: exit")
end

function s1f_enter()
	print("state 1: enter")
end

function s1f_process(event)
	print("state 1: process")
	sm:new_state(3)
end

function s1f_exit()
	print("state 1: exit")
end

function s2f_enter()
	print("state 2: enter")
end

function s2f_process(event)
	print("state 2: process")
	sm:new_state(2)
end

function s2f_exit()
	print("state 2: exit")
end

--------------------------------------------------------------------------------
--
--	The state machine
--
--------------------------------------------------------------------------------
st_mach_1 = {
	{	state="rose",	enter=def_enter,	proc=def_process,	exit=def_exit	},
	{	state="lilly",	enter=s1f_enter,	proc=s1f_process,	exit=s1f_exit	},
	{	state="tulip",	enter=s2f_enter,	proc=s2f_process,	exit=s2f_exit	}
}
st_mach_2 = {
	{	state="apple",	enter=def_enter,	proc=def_process,	exit=def_exit	},
	{	state="banana",	enter=s1f_enter,	proc=s1f_process,	exit=s1f_exit	},
	{	state="orange",	enter=s2f_enter,	proc=s2f_process,	exit=s2f_exit	}
}


--------------------------------------------------------------------------------
--
--	state machine processing
--
--------------------------------------------------------------------------------
sm = {}
function sm:new (o)									-- create a new object
	o = o or {}										-- create object if user does not provide one
	setmetatable(o, self)							-- set the meta-table for the object to self
	self.__index = self								-- set self.__index to self
	return o										-- return the object
end
function sm:initialize(i, j, n)
	self.c_state = i								-- initial state
	self.t_state = nil								-- set temp state to nil
	self.s_tab = j									-- set the state table
	self.name = n									-- set the state machine name
	self.s_tab[self.c_state].enter()				-- enter the initial state
end
function sm:new_state(new_state)					-- select a new state
	self.t_state = new_state						-- save the new state into the temp state
end
function sm:print_sm_name()							-- print the sm name
	print(self.name)								-- print the sm name
end
function sm:print_state_name()						-- print the state name
	print(self.s_tab[self.c_state].state)			-- print the state name
end
function sm:process(event)							-- process the current state
	self.s_tab[self.c_state].proc(event)			-- process the current state
	if self.t_state then							-- if the process changed the state
		self.s_tab[self.c_state].exit()				-- exit the current state
		self.c_state = self.t_state					-- set the new state
		self.s_tab[self.c_state].enter()			-- enter the next state
		self.t_state = nil							-- reset tmp state
	end
end

--------------------------------------------------------------------------------
--
--	the SM test application
--
--------------------------------------------------------------------------------
	a = sm:new()									-- create a new state machine object
	a:initialize(1,st_mach_1,"flower sm")			-- initialize all the local variables
	a:print_sm_name()								-- print the name of the SM
	for count=1,9 do								-- loop to process
		a:process(3)								-- process anything to demonstrate the SM
		a:print_state_name()						-- display the state name
	end												-- demo a done

	b = sm:new()									-- create a new state machine object
	b:initialize(1,st_mach_2,"fruit sm")			-- initialize all the local variables
	b:print_sm_name()								-- print the name of the SM
	for count=1,9 do								-- loop to process
		b:process(3)								-- process anything to demonstrate the SM
		b:print_state_name()						-- display the state name
	end												-- demo b done
